﻿/*
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at 
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  
 */

using System;
using java = biz.ritter.javapi;
using System.Collections.Generic;

namespace biz.ritter.javapi.util
{
    /// <summary>
    /// 
    /// </summary>
    public interface List : List<object>
    {
    }

    /**
     * A {@code List} is a collection which maintains an ordering for its elements. Every
     * element in the {@code List} has an index. Each element can thus be accessed by its
     * index, with the first index being zero. Normally, {@code List}s allow duplicate
     * elements, as compared to Sets, where elements have to be unique.
     */
    public interface List<E> : Collection<E> {
        /**
         * Inserts the specified object into this {@code List} at the specified location.
         * The object is inserted before the current element at the specified
         * location. If the location is equal to the size of this {@code List}, the object
         * is added at the end. If the location is smaller than the size of this
         * {@code List}, then all elements beyond the specified location are moved by one
         * position towards the end of the {@code List}.
         * 
         * @param location
         *            the index at which to insert.
         * @param object
         *            the object to add.
         * @throws UnsupportedOperationException
         *                if adding to this {@code List} is not supported.
         * @throws ClassCastException
         *                if the class of the object is inappropriate for this
         *                {@code List}.
         * @throws IllegalArgumentException
         *                if the object cannot be added to this {@code List}.
         * @throws IndexOutOfBoundsException
         *                if {@code location < 0 || location > size()}
         */
        void add(int location, E obj);

        /**
         * Adds the specified object at the end of this {@code List}.
         * 
         * @param object
         *            the object to add.
         * @return always true.
         * @throws UnsupportedOperationException
         *                if adding to this {@code List} is not supported.
         * @throws ClassCastException
         *                if the class of the object is inappropriate for this
         *                {@code List}.
         * @throws IllegalArgumentException
         *                if the object cannot be added to this {@code List}.
         */
        new bool add(E obj);

        /**
         * Inserts the objects in the specified collection at the specified location
         * in this {@code List}. The objects are added in the order they are returned from
         * the collection's iterator.
         * 
         * @param location
         *            the index at which to insert.
         * @param collection
         *            the collection of objects to be inserted.
         * @return true if this {@code List} has been modified through the insertion, false
         *         otherwise (i.e. if the passed collection was empty).
         * @throws UnsupportedOperationException
         *                if adding to this {@code List} is not supported.
         * @throws ClassCastException
         *                if the class of an object is inappropriate for this
         *                {@code List}.
         * @throws IllegalArgumentException
         *                if an object cannot be added to this {@code List}.
         * @throws IndexOutOfBoundsException
         *                if {@code location < 0 || > size()}
         */
        bool addAll(int location, Collection<E> collection);

        /**
         * Adds the objects in the specified collection to the end of this {@code List}. The
         * objects are added in the order in which they are returned from the
         * collection's iterator.
         * 
         * @param collection
         *            the collection of objects.
         * @return {@code true} if this {@code List} is modified, {@code false} otherwise
         *         (i.e. if the passed collection was empty).
         * @throws UnsupportedOperationException
         *                if adding to this {@code List} is not supported.
         * @throws ClassCastException
         *                if the class of an object is inappropriate for this
         *                {@code List}.
         * @throws IllegalArgumentException
         *                if an object cannot be added to this {@code List}.
         */
        new bool addAll(Collection<E> collection);

        /**
         * Removes all elements from this {@code List}, leaving it empty.
         * 
         * @throws UnsupportedOperationException
         *                if removing from this {@code List} is not supported.
         * @see #isEmpty
         * @see #size
         */
        new void clear();

        /**
         * Tests whether this {@code List} contains the specified object.
         * 
         * @param object
         *            the object to search for.
         * @return {@code true} if object is an element of this {@code List}, {@code false}
         *         otherwise
         */
        new bool contains(Object obj);

        /**
         * Tests whether this {@code List} contains all objects contained in the
         * specified collection.
         * 
         * @param collection
         *            the collection of objects
         * @return {@code true} if all objects in the specified collection are
         *         elements of this {@code List}, {@code false} otherwise.
         */
        new bool containsAll(Collection<E> collection);


        /**
         * Returns the element at the specified location in this {@code List}.
         * 
         * @param location
         *            the index of the element to return.
         * @return the element at the specified location.
         * @throws IndexOutOfBoundsException
         *                if {@code location < 0 || >= size()}
         */
        E get(int location);

        /**
         * Searches this {@code List} for the specified object and returns the index of the
         * first occurrence.
         * 
         * @param object
         *            the object to search for.
         * @return the index of the first occurrence of the object or -1 if the
         *         object was not found.
         */
        int indexOf(Object obj);

        /**
         * Returns whether this {@code List} contains no elements.
         * 
         * @return {@code true} if this {@code List} has no elements, {@code false}
         *         otherwise.
         * @see #size
         */
        new bool isEmpty();

        /**
         * Returns an iterator on the elements of this {@code List}. The elements are
         * iterated in the same order as they occur in the {@code List}.
         * 
         * @return an iterator on the elements of this {@code List}.
         * @see Iterator
         */
        new Iterator<E> iterator();

        /**
         * Searches this {@code List} for the specified object and returns the index of the
         * last occurrence.
         * 
         * @param object
         *            the object to search for.
         * @return the index of the last occurrence of the object, or -1 if the
         *         object was not found.
         */
        int lastIndexOf(Object obj);

        /**
         * Returns a {@code List} iterator on the elements of this {@code List}. The elements are
         * iterated in the same order that they occur in the {@code List}.
         * 
         * @return a {@code List} iterator on the elements of this {@code List}
         * 
         * @see ListIterator
         */
        ListIterator<E> listIterator();

        /**
         * Returns a list iterator on the elements of this {@code List}. The elements are
         * iterated in the same order as they occur in the {@code List}. The iteration
         * starts at the specified location.
         * 
         * @param location
         *            the index at which to start the iteration.
         * @return a list iterator on the elements of this {@code List}.
         * @throws IndexOutOfBoundsException
         *                if {@code location < 0 || location > size()}
         * @see ListIterator
         */
        ListIterator<E> listIterator(int location);

        /**
         * Removes the object at the specified location from this {@code List}.
         * 
         * @param location
         *            the index of the object to remove.
         * @return the removed object.
         * @throws UnsupportedOperationException
         *                if removing from this {@code List} is not supported.
         * @throws IndexOutOfBoundsException
         *                if {@code location < 0 || >= size()}
         */
        E remove(int location);

        /**
         * Removes the first occurrence of the specified object from this {@code List}.
         * 
         * @param object
         *            the object to remove.
         * @return true if this {@code List} was modified by this operation, false
         *         otherwise.
         * @throws UnsupportedOperationException
         *                if removing from this {@code List} is not supported.
         */
        new bool remove(Object obj);

        /**
         * Removes all occurrences in this {@code List} of each object in the specified
         * collection.
         * 
         * @param collection
         *            the collection of objects to remove.
         * @return {@code true} if this {@code List} is modified, {@code false} otherwise.
         * @throws UnsupportedOperationException
         *                if removing from this {@code List} is not supported.
         */
        new bool removeAll(Collection<E> collection);

        /**
         * Removes all objects from this {@code List} that are not contained in the
         * specified collection.
         * 
         * @param collection
         *            the collection of objects to retain.
         * @return {@code true} if this {@code List} is modified, {@code false} otherwise.
         * @throws UnsupportedOperationException
         *                if removing from this {@code List} is not supported.
         */
        new bool retainAll(Collection<E> collection);

        /**
         * Replaces the element at the specified location in this {@code List} with the
         * specified object. This operation does not change the size of the {@code List}.
         * 
         * @param location
         *            the index at which to put the specified object.
         * @param object
         *            the object to insert.
         * @return the previous element at the index.
         * @throws UnsupportedOperationException
         *                if replacing elements in this {@code List} is not supported.
         * @throws ClassCastException
         *                if the class of an object is inappropriate for this
         *                {@code List}.
         * @throws IllegalArgumentException
         *                if an object cannot be added to this {@code List}.
         * @throws IndexOutOfBoundsException
         *                if {@code location < 0 || >= size()}
         */
        E set(int location, E obj);

        /**
         * Returns the number of elements in this {@code List}.
         * 
         * @return the number of elements in this {@code List}.
         */
        new int size();

        /**
         * Returns a {@code List} of the specified portion of this {@code List} from the given start
         * index to the end index minus one. The returned {@code List} is backed by this
         * {@code List} so changes to it are reflected by the other.
         * 
         * @param start
         *            the index at which to start the sublist.
         * @param end
         *            the index one past the end of the sublist.
         * @return a list of a portion of this {@code List}.
         * @throws IndexOutOfBoundsException
         *                if {@code start < 0, start > end} or {@code end >
         *                size()}
         */
        List<E> subList(int start, int end);

        /**
         * Returns an array containing all elements contained in this {@code List}.
         * 
         * @return an array of the elements from this {@code List}.
         */
        new Object[] toArray();

        /**
         * Returns an array containing all elements contained in this {@code List}. If the
         * specified array is large enough to hold the elements, the specified array
         * is used, otherwise an array of the same type is created. If the specified
         * array is used and is larger than this {@code List}, the array element following
         * the collection elements is set to null.
         * 
         * @param array
         *            the array.
         * @return an array of the elements from this {@code List}.
         * @throws ArrayStoreException
         *                if the type of an element in this {@code List} cannot be stored
         *                in the type of the specified array.
         */
        new T[] toArray<T>(T[] array);

    }
}
